#include "stdafx.h"
#include "Scene.h"

#include "Camera.h"
#include "Node.h"

#include "RigidBody.h"

using namespace mscene;

Scene::Scene(mgfx::RenderingSystem & renderSys, mphys::PhysicsSystem & physSys)
	: RenderSys(renderSys), PhysSys(physSys)
{
	mCamera = new Camera;
}

Scene::~Scene()
{
	delete mCamera;
	for(size_t i = 0; i < mNodes.size(); i++)
		delete mNodes[i];
}

void Scene::addNode(Node & node)
{
	assert(&node);
	mNodes.push_back(&node);
}

void Scene::deleteNode(Node & node)
{
	assert(&node);
	for(size_t i = 0; i < mNodes.size(); i++)
	{
		if(mNodes[i] == &node)
		{
			delete mNodes[i];
			mNodes[i] = mNodes.back();
			mNodes.pop_back();
			return;
		}
		
	}
}

void Scene::update(float dt)
{
	float moveSpeed = 30.0f;
	float moveSide = 0.0f, moveForward = 0.0f, moveUp = 0.0f;
	if(GetAsyncKeyState('A') & 0x8000)	moveSide -= moveSpeed*dt;
	if(GetAsyncKeyState('D') & 0x8000)	moveSide += moveSpeed*dt;
	if(GetAsyncKeyState('W') & 0x8000)	moveForward += moveSpeed*dt;
	if(GetAsyncKeyState('S') & 0x8000)	moveForward -= moveSpeed*dt;
	if(GetAsyncKeyState('Q') & 0x8000)	moveUp += moveSpeed*dt;
	if(GetAsyncKeyState('E') & 0x8000)	moveUp -= moveSpeed*dt;


	if(moveSide != 0.0f) mCamera->strafe(moveSide * 5);
	if(moveForward != 0.0f) mCamera->walk(moveForward * 5);

	//if(GetAsyncKeyState('Q') & 0x8000)	mCamera->rotateY(-2.0f*dt);
	//if(GetAsyncKeyState('E') & 0x8000)	mCamera->rotateY(+2.0f*dt);
	//if(GetAsyncKeyState('F') & 0x8000)  mCamera->pitch(-2.0f*dt);
	//if(GetAsyncKeyState('R') & 0x8000)	mCamera->pitch(+2.0f*dt);
	// 

	mCamera->rebuildView();

	if(GetAsyncKeyState('P') & 0x8000)
		return;

	for each(auto node in mNodes)
	{
		node->update(dt);
	}
}


Node* mscene::Scene::getIntersectingNode( const mmath::Ray & ray )
{
	float closestDist = std::numeric_limits<float>::infinity();
	Node * closestNode = NULL;
	for(size_t i = 0; i < mNodes.size(); i++)
	{
		float dist = mNodes[i]->rayIntersection(ray);
		if(dist < closestDist && dist >= 0)
		{
			closestDist = dist;
			closestNode = mNodes[i];
		}
	}
	return closestNode;
}

Node* Scene::getNode( uint index )
{
	if(index >= 0 && index < mNodes.size())
		return mNodes[index];

	return NULL;
}

void Scene::mouseMove(int moveX, int moveY)
{
	mCamera->pitch(float(-moveY) * 0.01f);
	mCamera->rotateY(float(-moveX) * 0.01f);

}

bool Scene::keyEvent(util::KeyEvent event, WPARAM wParam, LPARAM lParam)
{
	return false;
}

void Scene::commitEditorChanges()
{
	for(uint i = 0; i < mNodes.size(); i++)
	{
		mNodes[i]->commitEditorChanges();
	}
}